namespace SimpleWebServices
{
    using System;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Formatters.Binary;
    using Xunit;

    public sealed class AbsoluteUriFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<AbsoluteUri>()
                .DerivesFrom<object>()
                .IsConcreteClass()
                .IsSealed()
                .NoDefaultConstructor()
                .Serializable()
                .Implements<IComparable>()
                .Implements<IComparable<AbsoluteUri>>()
                .Implements<IEquatable<AbsoluteUri>>()
                .Result);
        }

        [Fact]
        public void ctor_stringAbsolute()
        {
            Assert.NotNull(new AbsoluteUri("http://example.com/"));
        }

        [Fact]
        public void ctor_stringEmpty()
        {
            Assert.Throws<UriFormatException>(() => new AbsoluteUri(string.Empty));
        }

        [Fact]
        public void ctor_stringRelative()
        {
            Assert.Throws<UriFormatException>(() => new AbsoluteUri("/"));
        }

        [Fact]
        public void ctor_stringNull()
        {
            Assert.Throws<ArgumentNullException>(() => new AbsoluteUri(null as string));
        }

        [Fact]
        public void ctor_UriAbsolute()
        {
            Assert.NotNull(new AbsoluteUri(new Uri("http://example.com/")));
        }

        [Fact]
        public void ctor_UriRelative()
        {
            Assert.Throws<UriFormatException>(() => new AbsoluteUri(new Uri("/", UriKind.Relative)));
        }

        [Fact]
        public void ctor_UriNull()
        {
            Assert.Throws<ArgumentNullException>(() => new AbsoluteUri(null as Uri));
        }

        [Fact]
        public void ctor_SerializationInfo_StreamingContext()
        {
            AbsoluteUri expected = new AbsoluteUri("http://example.com");
            AbsoluteUri actual = null;

            using (Stream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, new AbsoluteUri("http://example.com"));
                stream.Position = 0;
                actual = (AbsoluteUri)formatter.Deserialize(stream);
            }

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opEquality_AbsoluteUri_AbsoluteUri()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.True(obj == comparand);
        }

        [Fact]
        public void opEquality_AbsoluteUri_AbsoluteUriDiffers()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.net/");

            Assert.False(obj == comparand);
        }

        [Fact]
        public void opEquality_AbsoluteUri_AbsoluteUriSame()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = obj;

            Assert.True(obj == comparand);
        }

        [Fact]
        public void opEquality_AbsoluteUriNull_AbsoluteUri()
        {
            AbsoluteUri obj = null;
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.False(obj == comparand);
        }

        [Fact]
        public void opEquality_AbsoluteUri_AbsoluteUriNull()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = null;

            Assert.False(obj == comparand);
        }

        [Fact]
        public void opInequality_AbsoluteUri_AbsoluteUri()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.False(obj != comparand);
        }

        [Fact]
        public void opInequality_AbsoluteUri_AbsoluteUriDiffers()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.net/");

            Assert.True(obj != comparand);
        }

        [Fact]
        public void opInequality_AbsoluteUri_AbsoluteUriSame()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = obj;

            Assert.False(obj != comparand);
        }

        [Fact]
        public void opInequality_AbsoluteUriNull_AbsoluteUri()
        {
            AbsoluteUri obj = null;
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.True(obj != comparand);
        }

        [Fact]
        public void opInequality_AbsoluteUri_AbsoluteUriNull()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = null;

            Assert.True(obj != comparand);
        }

        [Fact]
        public void opLesserThan_AbsoluteUri_AbsoluteUri()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.False(obj < comparand);
        }

        [Fact]
        public void opLesserThan_AbsoluteUri_AbsoluteUriLesser()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.net/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.False(obj < comparand);
        }

        [Fact]
        public void opLesserThan_AbsoluteUriLesser_AbsoluteUri()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.net/");

            Assert.True(obj < comparand);
        }

        [Fact]
        public void opLesserThan_AbsoluteUri_AbsoluteUriNull()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = null;

            Assert.False(obj < comparand);
        }

        [Fact]
        public void opLesserThan_AbsoluteUriNull_AbsoluteUri()
        {
            AbsoluteUri obj = null;
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.True(obj < comparand);
        }

        [Fact]
        public void opLesserThan_AbsoluteUriNull_AbsoluteUriNull()
        {
            AbsoluteUri obj = null;
            AbsoluteUri comparand = null;

            Assert.False(obj < comparand);
        }

        [Fact]
        public void opGreaterThan_AbsoluteUri_AbsoluteUri()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.False(obj > comparand);
        }

        [Fact]
        public void opGreaterThan_AbsoluteUriGreater_AbsoluteUri()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.net/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.True(obj > comparand);
        }

        [Fact]
        public void opGreaterThan_AbsoluteUri_AbsoluteUriGreater()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.net/");

            Assert.False(obj > comparand);
        }

        [Fact]
        public void opGreaterThan_AbsoluteUri_AbsoluteUriNull()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = null;

            Assert.True(obj > comparand);
        }

        [Fact]
        public void opGreaterThan_AbsoluteUriNull_AbsoluteUri()
        {
            AbsoluteUri obj = null;
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.False(obj > comparand);
        }

        [Fact]
        public void opGreaterThan_AbsoluteUriNull_AbsoluteUriNull()
        {
            AbsoluteUri obj = null;
            AbsoluteUri comparand = null;

            Assert.False(obj > comparand);
        }

        [Fact]
        public void opExplicit_string_AbsoluteUri()
        {
            string expected = "http://example.com/";
            string actual = (string)new AbsoluteUri(expected);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void opExplicit_string_AbsoluteUriNull()
        {
            string expected = null;
            string actual = (string)(null as AbsoluteUri);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void opExplicit_AbsoluteUri_string()
        {
            AbsoluteUri expected = new AbsoluteUri("http://example.com/");
            AbsoluteUri actual = (AbsoluteUri)"http://example.com/";

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opExplicit_AbsoluteUri_stringEmpty()
        {
            AbsoluteUri obj = null;

            Assert.Throws<UriFormatException>(() => (AbsoluteUri)(obj = string.Empty));
        }

        [Fact]
        public void opExplicit_AbsoluteUri_stringNull()
        {
            string value = null;

            AbsoluteUri expected = null;
            AbsoluteUri actual = (AbsoluteUri)value;

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opImplicit_string_AbsoluteUri()
        {
            string expected = "http://example.com/";
            string actual = new AbsoluteUri(expected);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void opImplicit_string_AbsoluteUriNull()
        {
            string expected = null;
            string actual = null as AbsoluteUri;

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void opImplicit_AbsoluteUri_string()
        {
            AbsoluteUri expected = new AbsoluteUri("http://example.com/");
            AbsoluteUri actual = "http://example.com/";

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opImplicit_AbsoluteUri_stringEmpty()
        {
            AbsoluteUri obj = null;

            Assert.Throws<UriFormatException>(() => (obj = string.Empty));
        }

        [Fact]
        public void opImplicit_AbsoluteUri_stringNull()
        {
            string value = null;

            AbsoluteUri expected = null;
            AbsoluteUri actual = value;

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opExplicit_Uri_AbsoluteUri()
        {
            Uri expected = new Uri("http://example.com/");
            Uri actual = (Uri)new AbsoluteUri(expected);

            Assert.Equal<Uri>(expected, actual);
        }

        [Fact]
        public void opExplicit_Uri_AbsoluteUriNull()
        {
            Uri expected = null;
            Uri actual = (Uri)(null as AbsoluteUri);

            Assert.Equal<Uri>(expected, actual);
        }

        [Fact]
        public void opExplicit_AbsoluteUri_UriAbsolute()
        {
            AbsoluteUri expected = new AbsoluteUri(new Uri("http://example.com/"));
            AbsoluteUri actual = (AbsoluteUri)new Uri("http://example.com/");

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opExplicit_AbsoluteUri_UriNull()
        {
            Uri value = null;

            AbsoluteUri expected = null;
            AbsoluteUri actual = (AbsoluteUri)value;

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opExplicit_AbsoluteUri_UriRelative()
        {
            AbsoluteUri obj = null;

            Assert.Throws<UriFormatException>(() => (AbsoluteUri)(obj = new Uri("/", UriKind.Relative)));
        }

        [Fact]
        public void opImplicit_Uri_AbsoluteUri()
        {
            Uri expected = new Uri("http://example.com/");
            Uri actual = new AbsoluteUri(expected);

            Assert.Equal<Uri>(expected, actual);
        }

        [Fact]
        public void opImplicit_Uri_AbsoluteUriNull()
        {
            Uri expected = null;
            Uri actual = null as AbsoluteUri;

            Assert.Equal<Uri>(expected, actual);
        }

        [Fact]
        public void opImplicit_AbsoluteUri_Uri()
        {
            AbsoluteUri expected = new AbsoluteUri("http://example.com/");
            AbsoluteUri actual = new Uri("http://example.com/");

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opImplicit_AbsoluteUri_UriNull()
        {
            Uri value = null;

            AbsoluteUri expected = null;
            AbsoluteUri actual = value;

            Assert.Equal<AbsoluteUri>(expected, actual);
        }

        [Fact]
        public void opImplicit_AbsoluteUri_UriRelative()
        {
            AbsoluteUri obj = null;

            Assert.Throws<UriFormatException>(() => (obj = new Uri("/", UriKind.Relative)));
        }

        [Fact]
        public void op_CompareTo_AbsoluteUri()
        {
            int expected = 1;
            int actual = new AbsoluteUri("http://example.com/").CompareTo(null as AbsoluteUri);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_AbsoluteUriEqual()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            int expected = 0;
            int actual = obj.CompareTo(comparand);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_AbsoluteUriGreater()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.net/");

            int expected = -11;
            int actual = obj.CompareTo(comparand);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_AbsoluteUriLesser()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.net/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            int expected = 11;
            int actual = obj.CompareTo(comparand);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_AbsoluteUriSame()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");

            int expected = 0;
            int actual = obj.CompareTo(obj);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_object()
        {
            int expected = 1;
            int actual = new AbsoluteUri("http://example.com/").CompareTo(null as object);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_objectEqual()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            object comparand = new AbsoluteUri("http://example.com/");

            int expected = 0;
            int actual = obj.CompareTo(comparand as object);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_objectGreater()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            object comparand = new AbsoluteUri("http://example.net/");

            int expected = -11;
            int actual = obj.CompareTo(comparand as object);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_objectLesser()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.net/");
            object comparand = new AbsoluteUri("http://example.com/");

            int expected = 11;
            int actual = obj.CompareTo(comparand as object);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_objectSame()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");

            int expected = 0;
            int actual = obj.CompareTo(obj as object);

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_CompareTo_objectString()
        {
            Assert.Throws<ArgumentOutOfRangeException>(() => new AbsoluteUri("http://example.com/").CompareTo("http://example.com/" as object));
        }

        [Fact]
        public void op_Equals_AbsoluteUriEqual()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.True(obj.Equals(comparand));
        }

        [Fact]
        public void op_Equals_AbsoluteUriUnequal()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.net/");

            Assert.False(obj.Equals(comparand));
        }

        [Fact]
        public void op_Equals_AbsoluteUriNull()
        {
            Assert.False(new AbsoluteUri("http://example.com/").Equals(null as AbsoluteUri));
        }

        [Fact]
        public void op_Equals_AbsoluteUriSame()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = obj;

            Assert.True(obj.Equals(comparand));
        }

        [Fact]
        public void op_Equals_object()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.com/");

            Assert.True(obj.Equals(comparand as object));
        }

        [Fact]
        public void op_Equals_objectDiffer()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");
            AbsoluteUri comparand = new AbsoluteUri("http://example.net/");

            Assert.False(obj.Equals(comparand as object));
        }

        [Fact]
        public void op_Equals_objectSame()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");

            Assert.True(obj.Equals(obj as object));
        }

        [Fact]
        public void op_Equals_objectNull()
        {
            Assert.False(new AbsoluteUri("http://example.com/").Equals(null as object));
        }

        [Fact]
        public void op_Equals_objectString()
        {
            Assert.False(new AbsoluteUri("http://example.com/").Equals("http://example.com/" as object));
        }

        [Fact]
        public void op_GetHashCode()
        {
            AbsoluteUri obj = new AbsoluteUri("http://example.com/");

            int expected = obj.ToString().GetHashCode();
            int actual = obj.GetHashCode();

            Assert.Equal<int>(expected, actual);
        }

        [Fact]
        public void op_ToString()
        {
            string expected = "http://example.com/";
            string actual = new AbsoluteUri(expected).ToString();

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_GetObjectData_SerializationInfoNull_StreamingContext()
        {
            StreamingContext context = new StreamingContext(StreamingContextStates.All);

            Assert.Throws<ArgumentNullException>(() => (new AbsoluteUri("http://example.com/") as ISerializable).GetObjectData(null as SerializationInfo, context));
        }

        [Fact]
        public void op_GetObjectData_SerializationInfo_StreamingContext()
        {
            SerializationInfo info = new SerializationInfo(typeof(AbsoluteUri), new FormatterConverter());
            StreamingContext context = new StreamingContext(StreamingContextStates.All);

            string expected = "http://example.com/";

            (new AbsoluteUri(expected) as ISerializable).GetObjectData(info, context);

            string actual = info.GetString("_value");

            Assert.Equal<string>(expected, actual);
        }
    }
}